local AddOnName, Env = ...; local ADDON, DT = Env[1], Env[1].development
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalGUI 			= LibStub("DiesalGUI-1.0")
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local pairs, ipairs							= pairs,ipairs
local type	 									= type
local gsub, sub, find, format 			= string.gsub, string.sub, string.find, string.format
local concat									= table.concat
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| RotationConfig |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| RotationConfig Pool |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local rotationConfigPool = {}
function ADDON:NewRotationConfig()	
	local newRotationConfig = next(rotationConfigPool)
	if not newRotationConfig then
		newRotationConfig = ADDON:constructRotationConfig()		
	else
		rotationConfigPool[newRotationConfig] = nil		
	end
		
	newRotationConfig:OnAcquire()	
	return newRotationConfig	
end
function ADDON:ReleaseRotationConfig(rotationConfig)
	rotationConfig:OnRelease()	
	rotationConfigPool[rotationConfig] = true	
end
-- ~~| RotationConfig StyleSheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local windowStyleSheet = {		
	
}
local dropdownStyleSheet = {
	['frame-arrow'] = {
		type			= 'texture',
		layer			= 'BORDER',
		alpha 		= 0,
	},
}
local ConSelectStyleSheet = {		
	['frame-highlight'] = {			
		type			= 'texture',
		layer			= 'BORDER',
		color			= 'ffffff',
		gradient		= 'VERTICAL',
		alpha 		= .07,
		alphaEnd		= .12,
		offset		= {0,0,0,nil},
		height		= 11,
	},
	['frame-inline'] = {		
		type			= 'outline',
		layer			= 'BORDER',
		gradient		= 'VERTICAL',	
		color			= 'ffffff',
		alpha 		= .03,
		alphaEnd		= .07,
		offset		= 0,	
	},		
	['frame-arrow'] = {
		type			= 'texture',
		layer			= 'BORDER',
		alpha 		= 0,
	},
}	
local lockButtonNormal = {
	type			= 'texture',
	alpha 		= .7,
}
local lockButtonOver = {
	type			= 'texture',
	alpha 		= 1,
}
local lockButtonDisabled = {
	type			= 'texture',
	alpha 		= .3,
}
-- ~~| RotationConfig Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local GREY75		= ADDON:GetTxtColor('c0c0c0')
local GREY50		= ADDON:GetTxtColor('808080')
local BLUE			= ADDON:GetTxtColor('00aaff')	
local ORANGE		= ADDON:GetTxtColor('e6c000') 
local PURPLE		= ADDON:GetTxtColor('9900e5') 
local RED			= ADDON:GetTxtColor('ff0000') 
local YELLOW		= ADDON:GetTxtColor('ffff00')

-- ~~| RotationConfig Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
	['OnAcquire'] = function(self)				
		self.settings = ADDON:TableCopy( self.defaults )					
		self:Show()		
	end,
	['OnRelease'] = function(self)				
		self.accordian:ReleaseChildren()
		self:Hide()
	end,
	['ApplySettings'] = function(self) -- only called on acquisition
		if not self.settings.db then return end -- JIC		
		
		self.accordian:ReleaseChildren()
		self.accordian:Build(self.settings.configTable)		
		self:UpdateOptions()
		self:UpdateVars()
		self:UpdateSetList()
		
		self.window:SetTitle(RED..AddOnName,GREY75..self.settings.configTable.name..BLUE..' '..self.settings.configTable.author)	
		self.lockButton:SetStyle('frame',{ type = 'texture', texCoord = {self.settings.db.lock and 11 or 12,5,16,256,128} })
		
		self.frame[self.settings.db.show and "Show" or "Hide"](self.frame)	
		self.frame:ClearAllPoints()
		if self.settings.db.top and self.settings.db.left then
			self.frame:SetPoint("TOP",UIParent,"BOTTOM",0,self.settings.db.top)
			self.frame:SetPoint("LEFT",UIParent,"LEFT",self.settings.db.left,0)
		else
			self.frame:SetPoint("CENTER",UIParent,"CENTER")
		end
		self.frame:SetWidth(self.settings.db.width or 200)		
	end,
	['SetSettings'] = function(self,configTable,db)
		self.settings.configTable	= configTable
		self.settings.db		= db
		self:ApplySettings()
	end,
	['UpdateOptions'] = function(self)	
		local db = self.settings.db	
		local option
		for s = 1, #self.accordian.children do			
			for o = 1 , #self.accordian.children[s].children do				
				option = self.accordian.children[s].children[o]
				option[db.lock and "Lock" or "Unlock"](option)
				option:SetDB(db.sets[db.currentSet][option.settings.optionTable.id],ADDON.db.profile.rotationConfigs)
			end
			self.accordian.children[s]:SetDB(db.sections)
		end		
	end,
	['UpdateVars'] = function(self)
		if not self.configVars:IsVisible() then return end		
		local option
		
		local vars = {format('%sConfigID: %s%s%s\n\nVariables for rotation developers\n',BLUE,GREY75,self.settings.configTable.id,GREY50,varUse)}
		for s = 1, #self.settings.configTable do
			for o = 1, #self.settings.configTable[s] do
				option = self.settings.configTable[s][o]
				if option.type:lower() ~= 'divider' then
					if option.toggle ~= false then
						vars[#vars+1] = GREY75..option.id..'_Enable'
					end
					
					if option.type:lower() == 'hotkey' then
						vars[#vars+1] = format('%sIsHotkeys%s( %s%s_Value %s)',PURPLE,ORANGE,GREY75,option.id,ORANGE)
					elseif option.type:lower() ~= 'toggle' then
						vars[#vars+1] = GREY75..option.id..'_Value'
					end					
				end				
			end
		end			
		self.scrollingEditBox:SetText(concat(vars,'\n'))
	end,
	['UpdateSetList'] = function(self)
		local db = self.settings.db
		for i = 1, #db.sets do
			self.settings.orderedSetList[i] = i
			self.settings.setList[i] = db.sets[i].name
		end
		self.setSelect:SetList(self.settings.setList,self.settings.orderedSetList)
		self.setSelect:SetValue(db.currentSet)
	end,
	['RenameSet'] = function(self,key,value)
		self.settings.db.configs[self.settings.activeConfigID].sets[key].name = value
		self:UpdateSetList()
	end,
	['Show'] = function(self)
		self.frame:Show()
	end,
	['Hide'] = function(self)
		self.frame:Hide()
	end,
}
-- ~~| RotationConfig Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function ADDON:constructRotationConfig()
	local self = {}	
	-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	self.defaults = {		
		orderedSetList = {},
		setList = {},	
	}
	-- ~~ Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	-- OnAcquire, OnRelease, OnHeightSet, OnWidthSet		
	-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	local window = DiesalGUI:Create('Window')	
	window:AddStyleSheet(windowStyleSheet)
	window:SetSettings({		
		footer			= true,
		headerHeight	= 17,
		footerHeight	= 24,
		height	 		= 35,		
		minWidth 		= 190,
		minHeight 		= 10,
		sizerWidth		= 10,
		sizerB			= false,
		sizerBR			= false,
	},true)	
	window:SetEventListener('OnSizeChanged', function(this,event,width,height)
		if not self.settings.db then return end
		self.settings.db.width 	= width		
	end)
	window:SetEventListener('OnDragStop', function(this,event,left,top)
		if not self.settings.db then return end
		self.settings.db.left 	= left
		self.settings.db.top 	= top
	end)
	window:SetEventListener('OnClose', function(this,event)
		self.settings.db.show = false
		-- AceConfigRegistry:NotifyChange(AddOnName)
	end)	
	self.frame = window.frame	
	
	local accordian = DiesalGUI:Create('ConAccordian')
	accordian:SetParentObject(window)	
	accordian:SetEventListener('OnHeightChange', function(this,event,height)	
		self.frame:SetHeight( (window.settings.height - window.content:GetHeight()) + height )			
	end)
	accordian:SetAllPoints()	

	local setSelect = DiesalGUI:Create('ComboBox')
	setSelect:SetParent(window.footer)
	setSelect:SetPoint('TOPLEFT',18,-5)
	setSelect:SetPoint('TOPRIGHT',-3,-5)
	setSelect:SetHeight(16)
	setSelect:SetEventListener('OnValueSelected', function(this,event,key)
		self.settings.db.currentSet = key
		self:UpdateOptions()
	end)
	setSelect:SetEventListener('OnRenameValue', function(this,event,key,value)
	-- 	local PQI_RENAMESET 	= StaticPopup_Show("PQI_RENAMESET")
	-- 	PQI_RENAMESET.key  	= key
	-- 	PQI_RENAMESET.value 	= value
	end)	
	setSelect.button:SetScript("OnEnter", function(this) 		
		GameTooltip:SetOwner(setSelect.button, "ANCHOR_TOPRIGHT",0,2)
		GameTooltip:AddLine('Select Set')		
		GameTooltip:Show()
	end)
	setSelect.button:SetScript("OnLeave", function(this) GameTooltip:Hide() end)
	setSelect.editBox:SetScript("OnEnter", function(this)		
		GameTooltip:SetOwner(setSelect.editBox, "ANCHOR_TOPRIGHT",0,2)
		GameTooltip:AddLine('Rename Set')		
		GameTooltip:Show()
	end)
	setSelect.editBox:SetScript("OnLeave", function(this) GameTooltip:Hide() end)

	local lockButton = DiesalGUI:Create('Button')
	lockButton:SetParent(window.footer)
	lockButton:SetPoint('TOPLEFT',0,-3)
	lockButton:RegisterForClicks("LeftButtonUp","RightButtonUp")
	lockButton:SetSettings({
		width			= 20,
		height		= 20,
	},true)
	lockButton:SetStyle('frame',{
		type			= 'texture',
		texFile		='DiesalGUIcons',
		texCoord		= {12,5,16,256,128},
		alpha 		= .7,
		offset		= {-2,nil,-2,nil},
		width			= 16,
		height		= 16,
	})
	lockButton:SetEventListener('OnEnter', 	function()
		lockButton:SetStyle('frame',lockButtonOver)		
		GameTooltip:SetOwner(lockButton.frame, "ANCHOR_TOPRIGHT",0,2)
		GameTooltip:AddLine('Lock Config')		
		GameTooltip:Show()
	end)
	lockButton:SetEventListener('OnLeave', 	function()
		lockButton:SetStyle('frame',lockButtonNormal)
		GameTooltip:Hide()
	end)
	lockButton:SetEventListener('OnDisable', 	function() lockButton:SetStyle('frame',lockButtonDisabled)	end)
	lockButton:SetEventListener('OnEnable', 	function() lockButton:SetStyle('frame',lockButtonNormal)		end)
	lockButton:SetEventListener('OnClick', 	function(this,event,button)
		if button == 'LeftButton' then
			self.settings.db.lock = not self.settings.db.lock	
			local option
			for s = 1, #self.accordian.children do			
				for o = 1 , #self.accordian.children[s].children do				
					option = self.accordian.children[s].children[o]
					option[self.settings.db.lock and "Lock" or "Unlock"](option)				
				end
			end		
			lockButton:SetStyle('frame',{ type = 'texture', texCoord = {self.settings.db.lock and 11 or 12,5,16,256,128} })
		else			
			local win = self.configVars
			win[win:IsVisible() and 'Hide' or 'Show'](win)
			self:UpdateVars()			
		end
	end)

	local configVars = DiesalGUI:Create('Window')
	configVars:SetSettings({
		height	 		= 300,
		width				= 500,
		minWidth 		= 500,
		minHeight 		= 200,
		sizerR			= false,
		sizerB			= false,
		sizerBRHeight	= 32,
		sizerBRWidth	= 32,
	},true)
	configVars:SetTitle(RED..AddOnName,GREY75..'Config Variables')	
	configVars:SetStyle('content-background',{
		type			= 'texture',
		layer			= 'BACKGROUND',
		color			= '171717',
		offset		= 0,
	})
	configVars.sizerBR:SetPoint("BOTTOMRIGHT",configVars.frame,"BOTTOMRIGHT",-8,0)
	configVars.sizerBR:SetFrameLevel(100)
	configVars:Hide()
	local scrollingEditBox = DiesalGUI:Create('ScrollingEditBox')
	scrollingEditBox:SetParentObject(configVars)
	scrollingEditBox:SetSettings({
		contentPadTop		= 4,
		contentPadBottom	= 3,
		contentPadLeft		= 3,
		contentPadRight	= 3,
	},true)
	scrollingEditBox:SetPoint('TOPLEFT',1,-1)
	scrollingEditBox:SetPoint('BOTTOMRIGHT',-2,1)
	-- ~~ Frames ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	self.window 				= window
	self.frame 					= window.frame
	
	self.accordian 			= accordian	
	self.setSelect 			= setSelect
	self.lockButton 			= lockButton
	self.configVars 			= configVars
	self.scrollingEditBox 	= scrollingEditBox
	-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	for method, func in pairs(methods) do
		self[method] = func
	end
	-- ~~ Style ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	-- self.textures = {}
	-- DiesalStyle:AddObjectStyleSheet(self,styleSheet)
	-- ~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	
	return self
end